﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;

namespace 端口扫描器
{
    public partial class MainForm : Form
    {
        private Dictionary<IPEndPoint, bool> m_任务集合 = new Dictionary<IPEndPoint, bool>();
        private int 最大线程数 = 300;
        private int 总任务数;
        private int xh成功 = 1;
        private int xh失败 = 1;
        Action<string, string, int> fun; // = new Action<string>(this.写成功信息);

        public MainForm()
        {
            InitializeComponent();

            this.fun = new Action<string, string, int>(this.写扫描结果信息);
        }

        private void btn开始_Click(object sender, EventArgs e)
        {
            this.txt耗时.Text = DateTime.Now.ToString("mm:ss");//开始时间
            this.xh成功 = 1;
            this.xh失败 = 1;
            this.txt失败.Text = "";
            this.txt成功.Text = "";

            try
            {
                //先计算任务集合
                this.m_任务集合.Clear();
                int ip范围1 = int.Parse(this.txtIP范围1.Text);
                int ip范围2 = int.Parse(this.txtIP范围2.Text);
                int ip范围3 = int.Parse(this.txtIP范围3.Text);
                int ip范围4 = int.Parse(this.txtIP范围4.Text);
                int port1 = int.Parse(this.txtPort1.Text);
                int port2 = int.Parse(this.txtPort2.Text);

                //txtIP模板为多行文本，分开处理
                string[] ip模板集合 = this.txtIP模板.Text.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
                foreach (string ip模板 in ip模板集合)
                {
                    string ip = ip模板.Trim();
                    if (ip.Contains(".") == false)
                        continue;  //没有点，不是合格的ip

                    for (int m = ip范围1; m <= ip范围2; m++)
                    {
                        for (int n = ip范围3; n <= ip范围4; n++)
                        {
                            for (int port = port1; port <= port2; port++)
                            {
                                string t = ip.Replace("?", m.ToString()).Replace("*", n.ToString()).Replace(" ", "").Trim();

                                IPEndPoint p = new IPEndPoint(IPAddress.Parse(t), port);
                                this.m_任务集合[p] = false;
                                //Application.DoEvents();
                            }
                        }
                    }
                }
                this.总任务数 = this.m_任务集合.Count;

                //分配任务，加锁保证任务分配完毕后，再开始
                lock (this)
                {
                    this.最大线程数 = int.Parse(this.txt并行线程数.Text);
                    System.Threading.ThreadPool.SetMaxThreads(this.最大线程数, this.最大线程数);
                    System.Threading.ThreadPool.SetMinThreads(this.最大线程数, this.最大线程数);
                    foreach (IPEndPoint ip in this.m_任务集合.Keys)
                    {
                        System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(this.扫描端口), ip);
                        Application.DoEvents();
                    }

                    //foreach (IPEndPoint ip in this.m_任务集合.Keys)
                    //{
                    //    System.Threading.ParameterizedThreadStart start = new System.Threading.ParameterizedThreadStart(this.扫描端口);
                    //    System.Threading.Thread t = new System.Threading.Thread(start);
                    //    t.Start(ip);
                    //    Application.DoEvents();
                    //}
                }
                this.txt状态.Text = "进行中。。。。";
                this.timer显示任务.Enabled = true;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void btn退出_Click(object sender, EventArgs e)
        {
            this.timer显示任务.Enabled = false;
            this.Close();
        }

        private void 扫描端口(object p)
        {
            IPEndPoint ip = p as IPEndPoint;
            try
            {
                TcpClient tcp = new TcpClient();
                tcp.Connect(ip);
                //连接成功，关闭
                tcp.Close();

                this.Invoke(this.fun, "成功", ip.Address.ToString(), ip.Port);
            }
            catch
            {
                //连接失败
                this.Invoke(this.fun, "失败", ip.Address.ToString(), ip.Port);
            }
            finally
            {
                lock (this)
                {
                    this.m_任务集合.Remove(ip);
                }
            }
        }

        private void 写扫描结果信息(string 类别, string ip, int port)
        {
            if (类别 == "成功")
            {
                this.txt成功.Text += $"{this.xh成功++}\t {ip}\t {port}\r\n";
            }
            if (类别 == "失败")
            {
                this.txt失败.Text += $"{this.xh失败++}\t {ip}\t {port}\r\n";
            }
        }

        private void timer显示任务_Tick(object sender, EventArgs e)
        {
            int m, n;
            System.Threading.ThreadPool.GetAvailableThreads(out m, out n);
            this.txt活动线程数.Text = (this.最大线程数 - m).ToString();
            System.Threading.ThreadPool.GetMaxThreads(out m, out n);

            this.txt剩余任务.Text = this.m_任务集合.Count.ToString() + " / " + this.总任务数;
            if (this.m_任务集合.Count == 0)
            {
                this.timer显示任务.Enabled = false;
                this.txt状态.Text = "任务已完成";
                this.txt耗时.Text += " --> "+DateTime.Now.ToString("mm:ss");//结束时间
                MessageBox.Show("扫描完成！", "消息", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }

        }

        private void MainForm_Load(object sender, EventArgs e)
        {

        }


    }
}
